package com.kgc.activityprovider.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.kgc.activiti.pojo.WorkFlow;
import com.kgc.activiti.util.FileUtil;
import com.kgc.activiti.util.ResponseMsg;
import com.kgc.activityprovider.config.ActivitiConfiguration;
import com.kgc.activityprovider.dao.WorkFlowMapper;
import com.kgc.activityprovider.feign.UserFeign;
import com.kgc.activityprovider.listener.MyExecutionListener;
import com.kgc.activityprovider.listener.MyTaskListener;
import com.kgc.activityprovider.service.WorkFlowService;
import com.kgc.basic.util.PageInfo;
import org.activiti.engine.*;
import org.activiti.engine.delegate.event.ActivitiEventType;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.StringReader;
import java.util.*;

@Service
public class WorkFlowServiceImpl implements WorkFlowService {

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private WorkFlowMapper workFlowMapper;

    @Autowired
    private ProcessEngine processEngine;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private TaskService taskService ;


    @Autowired
    private HistoryService historyService;


    @Value("${fileupload.pathdir}")
    private String fileUploadDir;
//    @Value("${fileupload.classpathdir}")
//    private String classpathDir;

    private Logger logger = LoggerFactory.getLogger(getClass());
    @Override
    public ResponseMsg exportWorkerFlow(WorkFlow workFlow, String xml) {
        ResponseMsg msg =new ResponseMsg();

        String oldStr = "camunda:assignee";
        String newStr = "activiti:assignee";
        String oldStr1 = "camunda:candidateGroups";
        String newStr1 = "activiti:candidateGroups";


        String insertStr="xmlns:activiti=\"http://activiti.org/bpmn\" ";
        int insertIndex = xml.indexOf("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");


        try {
            // 创建 DocumentBuilder 并解析 XML
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true); // 关键：启用命名空间支持
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new InputSource(new StringReader(xml)));
            // 创建 XPath 并设置命名空间上下文
            XPath xpath = XPathFactory.newInstance().newXPath();
            xpath.setNamespaceContext(new NamespaceContext() { // 直接实现匿名内部类
                @Override
                public String getNamespaceURI(String prefix) {
                    switch (prefix) {
                        case "bpmn2":
                            return "http://www.omg.org/spec/BPMN/20100524/MODEL";
                        case "xsi":
                            return "http://www.w3.org/2001/XMLSchema-instance";
                        case "activiti":
                            return "http://activiti.org/bpmn";
                        default:
                            return null;
                    }
                }

                @Override
                public String getPrefix(String namespaceURI) { return null; }

                @Override
                public Iterator<String> getPrefixes(String namespaceURI) { return null; }
            });
            // 使用 XPath 查询 process 节点的 id 属性
            String expression = "//bpmn2:process/@id";
            Node idNode = (Node) xpath.evaluate(expression, doc, XPathConstants.NODE);
            if (idNode != null) {
                String id = idNode.getNodeValue();
                logger.debug("提取的 ID: " + id);
                ResponseMsg msg1 = checkCodeExit(id);
                if(!(boolean)msg1.getData()){
                    return msg1;
                }


                String newXml1 = xml.replace(oldStr1,newStr1);
                String newXml = newXml1.replace(oldStr,newStr);
                StringBuffer stringBuffer = new StringBuffer(newXml);
                stringBuffer.insert(insertIndex,insertStr);

                String finalXml = stringBuffer.toString();

                String fileName =  UUID.randomUUID().toString()+".bpmn20.xml";
                File file = new File(fileUploadDir,fileName);

                file.createNewFile();
                FileUtil.write(finalXml,fileUploadDir+fileName,"utf-8");

                workFlow.setUrl(fileUploadDir+fileName);
                workFlow.setCode(id);
                int insertCount = workFlowMapper.exportWorkerFlow(workFlow);
                if(insertCount>0){
                    msg.setCode("200");
                    msg.setData(true);
                    Deployment deployment = repositoryService.createDeployment().addInputStream(fileName, new FileInputStream(fileUploadDir+fileName)).deploy();
                }else{
                    msg.setCode("201");
                    msg.setData(false);
                }
                return msg;
            }else {
                msg.setCode("流程编码不能为空");
                msg.setData(false);
                return msg;
            }


        }catch (Exception e){
            throw new RuntimeException(e);
        }

    }

    @Override
    public ResponseMsg getWorkFlowList(Map<String, Object> paramMap) {
        ResponseMsg msg = new ResponseMsg();
        logger.info("WorkFlowServiceImpl getWorkFlowList paramMap:"+paramMap);
        PageInfo<WorkFlow> pageInfo = new PageInfo<>();
        if(paramMap.containsKey("pageNo")){
            pageInfo.setPageNo(Integer.valueOf(paramMap.get("pageNo").toString()));
        }
        if(paramMap.containsKey("pageSize")){
            pageInfo.setPageSize(Integer.valueOf(paramMap.get("pageSize").toString()));
        }
        Page<Object> page = PageHelper.startPage(pageInfo.getPageNo(), pageInfo.getPageSize());
        List<WorkFlow> workFlowList = workFlowMapper.getWorkFlowList(paramMap);
        logger.debug("WorkFlowServiceImpl getWorkFlowList workFlowList:"+workFlowList);
        pageInfo.setPages(page.getPages());
        pageInfo.setTotal((int)page.getTotal());
        pageInfo.setList(workFlowList);
        logger.debug("WorkFlowServiceImpl getWorkFlowList pageInfo:"+pageInfo);
        msg.setCode("200");
        msg.setData(pageInfo);
        msg.setMsg("页面查询成功");
        return msg;
    }

    @Override
    public ResponseMsg showWorkFlow(String url) {
        ResponseMsg msg = new ResponseMsg();
        String xml = FileUtil.read(url, "utf-8");
        msg.setData(xml);
        return msg;
    }

    @Override
    public ResponseMsg editWorkFlow(WorkFlow workFlow, String xml) {
        ResponseMsg msg =new ResponseMsg();

        String oldStr = "camunda:assignee";
        String newStr = "activiti:assignee";

        String oldStr1 = "camunda:candidateGroups";
        String newStr1 = "activiti:candidateGroups";
        String insertStr="xmlns:activiti=\"http://activiti.org/bpmn\" ";
        int insertIndex = xml.indexOf("xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");

        String newXml1 = xml.replace(oldStr,newStr);
        String newXml = newXml1.replace(oldStr1,newStr1);
        StringBuffer stringBuffer = new StringBuffer(newXml);
        int resCount = newXml.indexOf("xmlns:activiti=\"http://activiti.org/bpmn\"");
        if(resCount==-1){
            stringBuffer.insert(insertIndex,insertStr);
        }

        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true); // 关键：启用命名空间支持
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(new InputSource(new StringReader(xml)));
            // 创建 XPath 并设置命名空间上下文
            XPath xpath = XPathFactory.newInstance().newXPath();
            xpath.setNamespaceContext(new NamespaceContext() { // 直接实现匿名内部类
                @Override
                public String getNamespaceURI(String prefix) {
                    switch (prefix) {
                        case "bpmn2":
                            return "http://www.omg.org/spec/BPMN/20100524/MODEL";
                        case "xsi":
                            return "http://www.w3.org/2001/XMLSchema-instance";
                        case "activiti":
                            return "http://activiti.org/bpmn";
                        default:
                            return null;
                    }
                }

                @Override
                public String getPrefix(String namespaceURI) { return null; }

                @Override
                public Iterator<String> getPrefixes(String namespaceURI) { return null; }
            });
            // 使用 XPath 查询 process 节点的 id 属性
            String expression = "//bpmn2:process/@id";
            Node idNode = (Node) xpath.evaluate(expression, doc, XPathConstants.NODE);
            if (idNode != null) {
                String id = idNode.getNodeValue();
                logger.debug("提取的 ID: " + id);
                ResponseMsg msg1 = checkCodeExit(id);
                if (!(boolean) msg1.getData() && !id.equals(workFlow.getCode())) {
                    return msg1;
                }

                workFlow.setCode(id);
                String finalXml = stringBuffer.toString();
                FileUtil.write(finalXml,workFlow.getUrl(),"utf-8");

                int updateCount = workFlowMapper.editWorkFlow(workFlow);
                if (updateCount > 0) {
                    msg.setCode("200");
                    msg.setData(true);

                } else {
                    msg.setCode("201");
                    msg.setData(false);
                }
                return msg;
            }else{
                msg.setCode("流程编码不能为空");
                msg.setData(false);
                return msg;
            }
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    //String code, Integer type
    @Override
    public ResponseMsg startProcess(Map<String,Object> params) {
        ResponseMsg msg = new ResponseMsg();
        msg.setCode("200");
        msg.setMsg("开启实例成功");
        String code = (String) params.get("code");
        Integer type = (Integer) params.get("type");
        Map<String, Object> variables = new HashMap<>();

        // 开启流程实例 (流程设计图唯一标识key）根据type获取key
        WorkFlow workFlow = workFlowMapper.selectWorkFlowByType(type);
        ProcessInstance processInstance=  ActivitiConfiguration.getSpringProcessEngineConfiguration().getRuntimeService().startProcessInstanceByKey(workFlow.getCode(),code,params);
        //启动流程实例
        logger.debug("WorkFlowServiceImpl startProcess 流程定义id：" + processInstance.getProcessDefinitionId());
        logger.debug("WorkFlowServiceImpl startProcess 流程实例id：" + processInstance.getId());
        return msg;
    }

    @Override
    public ResponseMsg selectWorkFlowByType(int type) {
        ResponseMsg msg = new ResponseMsg();
        logger.info("WorkFlowServiceImpl selectWorkFlowByType type:"+type);
        WorkFlow workFlow = workFlowMapper.selectWorkFlowByType(type);
        logger.debug("WorkFlowServiceImpl selectWorkFlowByType workFlow:"+workFlow);
        msg.setData(workFlow);
        return msg;
    }

    //String code
    @Override
    public ResponseMsg competeTask(Map<String,Object> param) {
        ResponseMsg msg = new ResponseMsg();
        logger.info("WorkFlowServiceImpl competeTask param:"+param);
        String code = (String) param.get("code");
        Integer checkManId = (Integer) param.get("checkManId");
        String checkManName = (String) param.get("checkManName");

      com.kgc.publiccommon.util.ResponseMsg responseMsg = userFeign.selectRoleById(checkManId);
        List<Map<String,String>> userRoles = (List<Map<String,String>>)responseMsg.getData();
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceBusinessKey(code)
                .singleResult();

        // 根据流程唯一标识 key 和 任务办理人 查询任务
        Task task = taskService.createTaskQuery().processInstanceBusinessKey(code)
                // 流程 Key
                // 查询 meng 的任务
                .singleResult();
        // 目前只有一条任务，则可以只获取一条
        // 4. 完成任务（任务id）
        //
        boolean flag = false;
        String roleName = "";//角色名
        List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
        for (IdentityLink link : identityLinks) {
            if (link.getGroupId()!=null && "candidate".equals(link.getType())) {
                for (Map<String,String> param1:userRoles){
                    if (link.getGroupId().equals(param1.get("roleName"))||"管理员".equals(param1.get("roleName"))){
                        flag = true;
                        roleName = param1.get("roleName");
                        break;
                    }
                }

            }
        }

        if (flag){
            taskService.claim(task.getId(), param.get("checkManId").toString());//认领
            boolean checkRes = (boolean)param.get("checkRes");
            param.put("checkRes", checkRes);
//            Map<String,Object> variables = new HashMap<>();
//            variables.put("approved", approved);
//            variables.put("className",className);
//            variables.put("reviewOpinion",reviewOpinion);
//            variables.put("approver",userId);
//            variables.put("docCode",code);
            taskService.complete(task.getId(), param);
            msg.setCode("200");
            msg.setMsg("workFlowService competeTask");
        }else{
            msg.setCode("401");
            msg.setMsg("当前登录用户不是当前流程的审核人");
            logger.debug("WorkInsServiceImpl completeProcess params:{}",param);
            return msg;
        }
        return msg;
    }

    @Override
    public ResponseMsg checkCodeExit(String code) {
        ResponseMsg msg = new ResponseMsg();
        logger.info("WorkFlowServiceImpl checkCodeExitOrNull code:"+code);
        WorkFlow workFlow = workFlowMapper.checkCodeExit(code);
        logger.debug("WorkFlowServiceImpl checkCodeExitOrNull workFlow:"+workFlow);
        if(workFlow==null){
            msg.setCode("200");
            msg.setData(true);
            msg.setMsg("工作流编码不存在");
        }else{
            msg.setCode("201");
            msg.setData(false);
            msg.setMsg("工作流编码存在");
        }
        logger.debug("WorkFlowServiceImpl checkCodeExitOrNull msg:"+msg);
        return msg;
    }

    @Override
    public ResponseMsg checkNameExit(String name) {
        ResponseMsg msg = new ResponseMsg();
        logger.info("WorkFlowServiceImpl checkNameExit name:"+name);
        WorkFlow workFlow = workFlowMapper.checkNameExit(name);
        logger.debug("WorkFlowServiceImpl checkNameExit workFlow:"+workFlow);


        if(workFlow==null){
            msg.setCode("200");
            msg.setData(true);
            msg.setMsg("工作流名字不存在");
        }else{
            msg.setCode("201");
            msg.setData(false);
            msg.setMsg("工作流名字存在");
        }
        logger.debug("WorkFlowServiceImpl checkCodeExitOrNull msg:"+msg);
        return msg;
    }

    @Override
    public ResponseMsg checkTypeExit(int type) {
        ResponseMsg msg = new ResponseMsg();
        logger.info("WorkFlowServiceImpl checkTypeExit type:"+type);
        WorkFlow workFlow = workFlowMapper.checkTypeExit(type);
        logger.debug("WorkFlowServiceImpl checkTypeExit workFlow:"+workFlow);
        if(workFlow==null){
            msg.setCode("200");
            msg.setData(true);
            msg.setMsg("工作流类型不存在");
        }else{
            msg.setCode("201");
            msg.setData(false);
            msg.setMsg("工作流类型存在");
        }
        logger.debug("WorkFlowServiceImpl checkTypeExit msg:"+msg);
        return msg;
    }

    @Override
    public ResponseMsg deployWorkFlow(String url) {
        ResponseMsg msg = new ResponseMsg();
        int index = url.indexOf("/process/")+10;
//        int index = url.indexOf("/workflow/")+10;
        String fileName = url.substring(index);
        try {
            Deployment deployment = repositoryService.createDeployment().addInputStream(fileName, new FileInputStream(url)).deploy();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        }

        msg.setCode("200");
        msg.setData(true);
        return msg;
    }

    @Override
    public ResponseMsg reSubmit(Map<String, Object> params) {
        ResponseMsg msg =   startProcess(params);
        return msg;
    }

}
